home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / emulator / bsvc-1.000 / bsvc-1 / bsvc-1.0.4 / src / SimHector / cpu / ALU.cxx next >
C/C++ Source or Header  |  1995-07-26  |  8KB  |  363 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // ALU.cxx - Arithmetic Logic Unit
  4. //
  5. // NOTE: This code is based on the Hector simulator code written
  6. //       by Greg DeHoogh on 17 February 1990.
  7. // 
  8. // By: Bradford W. Mott
  9. // December 4,1993
  10. //
  11. ///////////////////////////////////////////////////////////////////////////////
  12.  
  13. #include "ALU.hxx"
  14.  
  15. ///////////////////////////////////////////////////////////////////////////////
  16. // Compute a result with the given function and inputs
  17. ///////////////////////////////////////////////////////////////////////////////
  18. unsigned long ALU::Compute(ALUFunction fn, unsigned long a_bus,
  19.                            unsigned long b_bus)
  20. {
  21.    unsigned long result;
  22.  
  23.    switch (fn)
  24.    {
  25.       case ADD:
  26.       case ADD_NCC:
  27.         result = a_bus + b_bus;
  28.         break;
  29.  
  30.       case ADDC:
  31.         if(flags & C_FLAG)
  32.           result = a_bus + b_bus + 1;
  33.         else
  34.           result = a_bus + b_bus;
  35.         break;
  36.  
  37.       case SUB:
  38.       case SUB_NCC:
  39.       case CMP:
  40.         result = b_bus - a_bus;
  41.         break;
  42.  
  43.       case AND:
  44.         result = a_bus & b_bus;
  45.         break;
  46.  
  47.       case SUBC:
  48.         if(flags & C_FLAG)
  49.           result = b_bus - a_bus - 1;
  50.         else
  51.           result = b_bus - a_bus;
  52.         break;
  53.  
  54.       case OR:
  55.         result = a_bus | b_bus;
  56.         break;
  57.  
  58.       case XOR:
  59.         result = a_bus ^ b_bus;
  60.         break;
  61.  
  62.       case NOT_A:
  63.         result = ~a_bus;
  64.         break;
  65.  
  66.       case NEG_A:
  67.         result = -a_bus;
  68.         // Set the Carry Flag
  69.         if((result % 0x10000) == 0)
  70.           flags |= C_FLAG;
  71.         else
  72.           flags &= ~C_FLAG;
  73.  
  74.         // Set the Overflow Flag
  75.         if(a_bus == 0x8000)
  76.           flags |= V_FLAG;
  77.         else
  78.           flags &= ~V_FLAG;
  79.         break;
  80.  
  81.       case INC_A:
  82.         result = a_bus + 1;
  83.         // Set the Carry Flag
  84.         if((result % 0x10000) == 0)
  85.           flags |= C_FLAG;
  86.         else
  87.           flags &= ~C_FLAG;
  88.  
  89.         // Set the Overflow Flag
  90.         if(a_bus == 0x8000)
  91.           flags |= V_FLAG;
  92.         else
  93.           flags &= ~V_FLAG;
  94.         break;
  95.  
  96.       case INC_A_NCC:
  97.         result = a_bus + 1;
  98.         break;
  99.  
  100.       case INC_B_NCC:
  101.         result = b_bus + 1;
  102.         break;
  103.  
  104.       case DEC_A:
  105.         result = a_bus - 1;
  106.         // Set the Carry Flag
  107.         if(a_bus == 0)
  108.           flags |= C_FLAG;
  109.         else
  110.           flags &= ~C_FLAG;
  111.  
  112.         // Set the Overflow Flag
  113.         if(a_bus == 0x8000)
  114.           flags |= V_FLAG;
  115.         else
  116.           flags &= ~V_FLAG;
  117.         break;
  118.  
  119.       case DEC_A_NCC:
  120.         result = a_bus - 1;
  121.         break;
  122.  
  123.       case DEC_B_NCC:
  124.         result = b_bus - 1;
  125.         break;
  126.  
  127.       case SHL_A:
  128.         result = a_bus << 1;
  129.         // Set the Carry Flag
  130.         if(a_bus & 0x8000)
  131.           flags |= C_FLAG;
  132.         else
  133.           flags &= ~C_FLAG;
  134.         break;
  135.  
  136.       case ROL_A:
  137.         if(flags & C_FLAG)
  138.           result = (a_bus << 1) | 1;
  139.         else
  140.           result = a_bus << 1;
  141.  
  142.         // Set the Carry Flag
  143.         if(a_bus & 0x8000)
  144.           flags |= C_FLAG;
  145.         else
  146.           flags &= ~C_FLAG;
  147.         break;
  148.  
  149.       case SHR_A:
  150.         result = (a_bus >> 1) | (a_bus & 0x8000);
  151.  
  152.         // Set the Carry Flag
  153.         if(a_bus & 1)
  154.           flags |= C_FLAG;
  155.         else
  156.           flags &= ~C_FLAG;
  157.         break;
  158.  
  159.       case ROR_A:
  160.         if(flags & C_FLAG)
  161.           result = (a_bus >> 1) | 0x8000;
  162.         else
  163.           result = a_bus >> 1;
  164.  
  165.         // Set the Carry Flag
  166.         if(a_bus & 1)
  167.           flags |= C_FLAG;
  168.         else
  169.           flags &= ~C_FLAG;
  170.         break;
  171.  
  172.       case BTST:
  173.         result = a_bus & b_bus;
  174.         break;
  175.  
  176.       case PASS_A:
  177.       case PASS_A_NCC:
  178.         result = a_bus;
  179.         break;
  180.  
  181.       case SWAP_A:
  182.         result = (a_bus >> 8) + ((a_bus & 0x00ff) << 8);
  183.         break;
  184.  
  185.       case CC_OUT:
  186.         result = flags;
  187.         break;
  188.  
  189.       case A_CC:
  190.         flags = a_bus & 0xf800;
  191.         result = 0;
  192.         break;
  193.  
  194.       default:
  195.         result = 0;
  196.    }
  197.  
  198.    /* Set the flags that were not set above */
  199.    switch (fn) {
  200.       case ADD:
  201.       case ADDC:
  202.       case SUB:
  203.       case SUBC:
  204.       case CMP:
  205.          // Set the Carry Flag
  206.          if(result > 0xffff)
  207.            flags |= C_FLAG;
  208.          else
  209.            flags &= ~C_FLAG;
  210.  
  211.          // Set the Negative Flag
  212.          if(result & 0x8000)
  213.            flags |= N_FLAG;
  214.          else
  215.            flags &= ~N_FLAG;
  216.  
  217.          // Set the Zero Flag
  218.          if(result & 0xffff)
  219.            flags &= ~Z_FLAG;
  220.          else
  221.            flags |= Z_FLAG;
  222.  
  223.          switch (fn) {
  224.             case ADD:
  225.             case ADDC:
  226.                // Set the Overflow Flag
  227.                if (((a_bus & 0x8000) == (b_bus & 0x8000)) && 
  228.                  ((a_bus & 0x8000) != (result & 0x8000)))
  229.                   flags |= V_FLAG;
  230.                else
  231.                   flags &= ~V_FLAG;
  232.                break;
  233.  
  234.             case SUB:
  235.             case SUBC:
  236.             case CMP:
  237.                // Set the Overflow flag 
  238.                if (((a_bus & 0x8000) != (b_bus & 0x8000)) &&
  239.                  ((a_bus & 0x8000) == (result & 0x8000)))
  240.                   flags |= V_FLAG;
  241.                else
  242.                   flags &= ~V_FLAG;
  243.  
  244.             default:
  245.               break;
  246.          }
  247.          break;
  248.  
  249.       case AND:
  250.       case OR:
  251.       case XOR:
  252.       case NOT_A:
  253.       case NEG_A:
  254.       case INC_A:
  255.       case DEC_A:
  256.       case BTST:
  257.       case SWAP_A:
  258.       case SHL_A:
  259.       case ROL_A:
  260.       case SHR_A:
  261.       case ROR_A:
  262.       case PASS_A:
  263.          // Set the Negative Flag
  264.          if(result & 0x8000)
  265.            flags |= N_FLAG;
  266.          else
  267.            flags &= ~N_FLAG;
  268.  
  269.          // Set the Zero Flag
  270.          if(result & 0xffff)
  271.            flags &= ~Z_FLAG;
  272.          else
  273.            flags |= Z_FLAG;
  274.          break;
  275.  
  276.       default:
  277.         break;
  278.    }
  279.    return(result & 0xffff);
  280. }
  281.  
  282. ///////////////////////////////////////////////////////////////////////////////
  283. // Test the given Condition Code and returns true if it passes
  284. ///////////////////////////////////////////////////////////////////////////////
  285. int ALU::TestConditionCode(ALUConditionCode cc, const char* &description)
  286. {
  287.    switch(cc)
  288.    {
  289.       case CC_VC:             // overflow clear
  290.          description=".VC";
  291.          return(!(flags & V_FLAG));
  292.  
  293.       case CC_PL:             // plus
  294.          description=".PL";
  295.          return(!(flags & N_FLAG));
  296.  
  297.       case CC_GE:             // greater than or equal (signed)
  298.          description=".GE";
  299.          return(((flags & N_FLAG) && (flags & V_FLAG)) ||
  300.                 (!(flags & N_FLAG) && !(flags & V_FLAG)));
  301.  
  302.       case CC_F:              // false
  303.          description=".F";
  304.          return 0;
  305.  
  306.       case CC_LE:             // less than or equal (signed)
  307.          description=".LE";
  308.          return((flags & Z_FLAG) || ((flags & N_FLAG) && !(flags & V_FLAG)) ||
  309.                 (!(flags & N_FLAG) && (flags & V_FLAG)));
  310.  
  311.       case CC_NE:             // not equal
  312.          description=".NE";
  313.          return(!(flags & Z_FLAG));
  314.  
  315.       case CC_LS:             // less than or same (unsigned)
  316.          description=".LS";
  317.          return((flags & C_FLAG) || (flags & Z_FLAG));
  318.  
  319.       case CC_CC:             // carry clear
  320.          description=".CC";
  321.          return(!(flags & C_FLAG));
  322.  
  323.       case CC_VS:             // overflow set
  324.          description=".VS";
  325.          return(flags & V_FLAG);
  326.  
  327.       case CC_MI:             // minus
  328.          description=".MI";
  329.          return(flags & N_FLAG);
  330.  
  331.       case CC_LT:             // less than (signed)
  332.          description=".LT";
  333.          return(((flags & N_FLAG) && !(flags & V_FLAG)) ||
  334.                 (!(flags & N_FLAG) && (flags & V_FLAG)));
  335.  
  336.       case CC_T:              // true
  337.          description=".T";
  338.          return 1;
  339.  
  340.       case CC_GT:             // greater than (signed)
  341.          description=".GT";
  342.          return(((flags & N_FLAG) && (flags & V_FLAG) && !(flags & Z_FLAG)) ||
  343.                 (!(flags & N_FLAG) && !(flags & V_FLAG) && !(flags & Z_FLAG)));
  344.  
  345.       case CC_EQ:             // equal
  346.          description=".EQ";
  347.          return(flags & Z_FLAG);
  348.  
  349.       case CC_HI:             // higher (unsigned)
  350.          description=".HI";
  351.          return(!(flags & C_FLAG) && !(flags & Z_FLAG));
  352.  
  353.       case CC_CS:             // carry set
  354.          description=".CS";
  355.          return(flags & C_FLAG);
  356.  
  357.       default:
  358.         description=".??";
  359.         return(0);
  360.    }
  361. }
  362.  
  363.